import { NEW_USER } from '@kuiper/auth';
import errorCodesBuilder from '../../../helpers/errorCodesBuilder';
import BalanceBuilder from './Balance';
import PackageBuilder from './Package';

const errorCodes = errorCodesBuilder();

export default function schemaBuilder(server) {
	[PackageBuilder, BalanceBuilder].forEach(x => x(server));

	/**
	 * 用户关联购买的套餐
	 */
	const {
		app: {
			graphqlResolvers,
			schemaComposer,
			model: { Balance },
			schema: { User: UserSchema, Balance: BalanceSchema },
		},
	} = server;

	graphqlResolvers.Query.UserPagination = graphqlResolvers.Query.UserPagination.addFilterArg(
		{
			name: `planExpireTime`,
			type: '[String]',
			description: 'target',
			query: async (query, value) => {
				const check =
					value[0] === 'in'
						? { planExpireTime: { $gt: Date() } }
						: { planExpireTime: { $lt: Date() } };
				const docs = await Balance.find(check).lean();
				query._id = { $in: docs.map(x => x.uid) };
			},
		}
	);

	UserSchema.addRelation('plan', {
		prepareArgs: {
			uid: source => source._id,
		},
		projection: { _id: 1 },
		resolver: () =>
			schemaComposer.createResolver({
				name: 'UserPlan',
				type: 'Package',
				args: {
					uid: 'MongoID',
				},
				resolve: async ({ args: { uid }, context: { request } }) => {
					const {
						server: {
							app: {
								model: { Balance, Package },
							},
						},
					} = request;

					try {
						const balance = await Balance.findOne({ uid }).lean();
						const planExpireTime = balance?.planExpireTime || null;
						const pkg = await Package.findOne({ _id: balance?.planId }).lean();
						if (pkg) {
							return { ...pkg, planExpireTime };
						} else {
							return pkg;
						}
					} catch (err) {
						const error = errorCodes['[12]查询用户关联套餐失败'].from(err);
						request.log.error({ error, uid }, error.rawMessage);
						throw error;
					}
				},
			}),
	});
	UserSchema.addRelation('balance', {
		resolver: () => BalanceSchema.mongooseResolvers.dataLoader({ lean: true }),
		prepareArgs: {
			uid: source => source._id,
		},
		projection: { _id: 1 },
	});

	/**
	 * 创建新用户时，初始化余额信息
	 */
	server.events.on(NEW_USER, async user => {
		server.log.info({ user: user.username }, '初始化新用户余额信息');
		try {
			await server.methods.initBalance({ uid: user._id });
		} catch (err) {
			const error = errorCodes[
				'[0F]初始化新用户套餐: 初始化Mongo记录失败'
			].from(err);
			server.log.error({ error }, error.rawMessage);
		}
	});
}
